<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-05-08
 * Time: 10:59
 */

namespace app\admin\model;


use app\admin\model\traits\ConfigBase;
use app\common\exception\ParameterException;
use app\common\model\BaseModel;
use app\common\validate\IDCollection;
use app\common\validate\IDMustBeRequire;
use service\TreeService;
use think\model\concern\SoftDelete;
use app\admin\validate\Configs as Validate;

class SystemConfig extends BaseModel
{
    protected const SYSTEM_CONFIG_KEY = "system_config";

    protected $hidden = ['update_time','delete_time'];

    use SoftDelete;
    protected $deleteTime = 'delete_time';

    use ConfigBase;

    public static function getTableTreeData(array $params)
    {
        $static = new static();

        $static = $static->order('sort','asc');

        foreach ($params as $name => $value) {
            $value = trim($value);
            switch ($name) {
                case 'cn_name':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('cn_name', $like_text);
                    }
                    break;
                case 'en_name':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('en_name', $like_text);
                    }
                    break;
                case 'pid':
                    if (!empty($value)) {
                        $static = $static->where('pid','=',intval($value));
                    }
                    break;
            }
        }

        $data = $static->select();

        $data = $data ? $data->toArray() : [];

        return TreeService::elementTableTree($data);
    }

    /**
     * 根据id获取对应的数据
     * @param $id
     * @return mixed
     */
    public static function getByID($id)
    {
        $validate = new IDMustBeRequire();
        if (!$validate->check(['id' => $id])) {
            throw new ParameterException([
                'msg' => $validate->getError()
            ]);
        }

        $data = static::where('id','=',$id)
            ->find()
            ->getData();

        return $data;
    }

    /**
     * 获取配置设置菜单的数据
     * @return array
     */
    public static function getConfigMenuData()
    {
        $data = static::where('status','=', 1)
            ->order('sort','asc')
            ->select();
        $data = $data ? $data->toArray() : [];

        return TreeService::listToTree($data);
    }

    /**
     * 获取配置的全部父节点信息
     * @return array
     */
    public static function getAllConfigParentNode()
    {
        $data = static::where([['pid','=',0],['status','=',1]])
            ->field(['id','cn_name'])
            ->order('sort','asc')
            ->select();

        if ($data) {
            return $data->toArray();
        } else {
            return [];
        }
    }

    /**
     * 添加配置项信息
     * @param array $data
     * @return bool
     */
    public static function addConfig(array $data)
    {
        $validate = new Validate();
        if (!$validate->scene('add')->check($data)) {
            throw new ParameterException([
                'msg' => $validate->getError()
            ]);
        }

        self::handleAddDefaultValue($data);

        $static = new static();
        $result = $static->allowField(['pid','cn_name','en_name','values','tips','value','type','sort','status'])
            ->save($data);

        if ($result !== false) {
            self::updateConfigValue();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 编辑配置项信息
     * @param array $data
     * @return bool
     */
    public static function editConfig(array $data)
    {
        $validate = new Validate();
        if (!$validate->scene('edit')->check($data)) {
            throw new ParameterException([
                'msg' => $validate->getError()
            ]);
        }

        // 获取旧数据
        $static = static::find($data['id']);
        $old_data = !empty($static) ? $static->toArray() : [];

        // 如果当前修改的是顶级元素，或者该元素下有子元素（在修改了父级元素时进行判断）
        self::checkTopHaveChild($data['id'], $old_data['pid'], $data['pid']);

        // 判断配置项类型是否发生了改变
        self::handleEditChangeType($old_data, $data);

        $result = $static->allowField(['id','pid','cn_name','en_name','values','tips','value','type','sort','status'])
            ->save($data);

        if ($result !== false) {
            self::updateConfigValue();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 删除指定id的配置项信息
     * @param $ids
     * @return bool
     */
    public static function delConfig($ids)
    {
        $validate = new IDCollection();
        if (!$validate->check([
            'ids' => $ids
        ])) {
            throw new ParameterException([
                'msg' => $validate->getError()
            ]);
        }

        // 获取全部菜单的id和pid数据
        $allConfigData = static::getDataWithField([],['id','pid'])
            ->toArray();
        $allID = [];    //保存所有的相关id，如果是顶级节点会获取其下面的子元素
        //判断是否为数组，然后将字符串转为数组
        if (!is_array($ids)){
            $ids = explode(',',$ids);
        }
        foreach ($ids as &$id) {
            //将id数组的字符转换成整数
            $id = intval($id);
            //判断是否有重复的数据
            if (in_array($id,$allID)){
                continue;
            }

            //获取对应id下的子id
            $allID = array_merge($allID,TreeService::getChildrenPid($allConfigData,$id,'id','pid',true));
        }
        //把主id也添加进去
        $allID = array_merge($allID,$ids);
        //去除重复值
        $allID = array_unique($allID);

        // 获取需要删除id的类型和值
        $allConfigValueData = static::getDataWithField([['id','in',$allID]],['id','type','value']);
        $allConfigValueData = !empty($allConfigValueData) ? $allConfigValueData->toArray() : [];

        // 对需要删除的节点进行处理
        self::handleDeleteFile($allConfigValueData);

        if (static::destroy($allID) !== false) {
            self::updateConfigValue();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新配置的值
     * @param array $data
     * @return bool
     */
    public static function commitConfigData(array $data)
    {
        // 处理指定的字段数据

        // 取出配置项的相关信息
        $configTypeData = self::getDataWithField([['pid','<>',0],['status','=',1]], ['id','en_name','type']);
        $configTypeData = !empty($configTypeData) ? $configTypeData->toArray(): [];

        $configCommitData = []; // 保存待提交的数据
        $needDeleteFiles = [];  // 保存需要删除的文件信息

        foreach ($configTypeData as $key => $value) {
            $configCommitData[$key]['id'] = $value['id'];
            $configCommitData[$key]['type'] = $value['type'];
            // 对不同的类型进行处理，防止用户乱输入
            switch($value['type']) {
                case 5:
                case 6:
                    $configCommitData[$key]['value'] = remove_xss($data[$value['en_name']]);
                    break;
                default:
                    $configCommitData[$key]['value'] = $data[$value['en_name']];
                    break;
            }
            // 检查图片是否需要删除
            switch ($value['type']) {
                // 删除富文本中被替换的图片
                case 6:
                    $old_value = static::field(['id','value'])
                        ->find($value['id'])
                        ->getData('value');
                    if (!empty($old_value)) {
                        $old_image = self::getRichTextImage($old_value);
                        $new_image = self::getRichTextImage($data[$value['en_name']]);

                        $needDeleteFiles = array_merge($needDeleteFiles, self::getDifferentFileWithArray($old_image, $new_image));
                    }
                    break;
                // 删除附件中不一样的数据
//                case 9:
//                    $old_value = static::field(['id','value'])
//                        ->find($value['id'])
//                        ->getData('value');
//                    if (!empty($old_value)) {
//                        $needDeleteFiles = array_merge($needDeleteFiles, self::getDifferentFileWithArray($old_value, $data[$value['en_name']]));
//                    }
//                    break;
            }
        }

        // 保存信息到数据库中
        $static = new static();
        $result = $static->saveAll($configCommitData);

        if ($result !== false) {
            // 删除旧图片数据
            delFile($needDeleteFiles);
            self::updateConfigValue();
            return true;
        } else {
            return false;
        }

    }
}